#include "log.h"

#include "../compiler/diksamc.h"

#define print(xx, args...) fprintf(stderr, xx, ##args)

#define println(xx, args...) fprintf(stderr, xx "\n", ##args)

DKC_Compiler *compiler;






// struct TypeSpecifier_tag {
//     DVM_BasicType       basic_type;
//     TypeDerive  *derive;
// };

// typedef enum {
//     DVM_BOOLEAN_TYPE,
//     DVM_INT_TYPE,
//     DVM_DOUBLE_TYPE,
//     DVM_STRING_TYPE
// } DVM_BasicType;

static char typeStr[1024] = "";
static char typeName[][64] = {
    "boolean",
    "int",
    "double",
    "string",
    "null"
    };
static int typeNameSize = sizeof(typeName) / sizeof(typeName[0]);
static const  char *getTypenameStr(int index)
{
    if (index < 0 || index >= typeNameSize)
    {
        index = typeNameSize - 1;
    }
    return typeName[index];
}

// typedef struct TypeDerive_tag {
//     DeriveTag   tag;
//     union {
//         FunctionDerive  function_d;
//     } u;
//     struct TypeDerive_tag       *next;
// } TypeDerive;

const char *getTypeStr(TypeSpecifier *type)
{
    DVM_BasicType basic_type = type->basic_type;
    TypeDerive *derive = type->derive;

    snprintf(typeStr, 1024, "%s", getTypenameStr(basic_type));


    while(derive)
    {
        print("derive");
        derive= derive->next;
    }

    return typeStr;
}


// typedef struct ParameterList_tag {
//     char                *name;
//     TypeSpecifier       *type;
//     int                 line_number;
//     struct ParameterList_tag *next;
// } ParameterList;

void print_para(ParameterList *para)
{
    print("%s %s,",  getTypeStr(para->type), para->name);
}

/*
struct FunctionDefinition_tag {
    TypeSpecifier       *type;
    char                *name;
    ParameterList       *parameter;
    Block               *block;
    int                 local_variable_count;
    Declaration         **local_variable;
    int                 index;
    struct FunctionDefinition_tag       *next;
};

*/
void print_function(FunctionDefinition *func)
{
    print("function:%s(", func->name);
    ParameterList *para = func->parameter;
    while (para)
    {
        print_para(para);
        para = para->next;
    }
    print(")\n");
}

// typedef struct DeclarationList_tag {
//     Declaration *declaration;
//     struct DeclarationList_tag *next;
// } DeclarationList;

// typedef struct {
//     char        *name;
//     TypeSpecifier       *type;
//     Expression  *initializer;
//     int variable_index;
//     DVM_Boolean is_local;
// } Declaration;


void print_declaration(DeclarationList *declartaionList)
{
    Declaration *declaration = declartaionList->declaration;
    println("[declaration][%s %s][index=%d,local=%d]", 
        getTypeStr(declaration->type), declaration->name,
        declaration->variable_index, declaration->is_local);        
}


// typedef struct StatementList_tag {
//     Statement   *statement;
//     struct StatementList_tag    *next;
// } StatementList;

// struct Expression_tag {
//     TypeSpecifier *type;
//     ExpressionKind kind;
//     int line_number;
//     union {
//         DVM_Boolean             boolean_value;
//         int                     int_value;
//         double                  double_value;
//         DVM_Char                *string_value;
//         IdentifierExpression    identifier;
//         CommaExpression         comma;
//         AssignExpression        assign_expression;
//         BinaryExpression        binary_expression;
//         Expression              *minus_expression;
//         Expression              *logical_not;
//         FunctionCallExpression  function_call_expression;
//         IncrementOrDecrement    inc_dec;
//         CastExpression          cast;
//     } u;
// };


// struct Statement_tag {
//     StatementType       type;
//     int                 line_number;
//     union {
//         Expression      *expression_s;
//         IfStatement     if_s;
//         WhileStatement  while_s;
//         ForStatement    for_s;
//         ForeachStatement        foreach_s;
//         BreakStatement  break_s;
//         ContinueStatement       continue_s;
//         ReturnStatement return_s;
//         TryStatement    try_s;
//         ThrowStatement  throw_s;
//         Declaration     *declaration_s;
//     } u;
// };

// typedef enum {
//     EXPRESSION_STATEMENT = 1,
//     IF_STATEMENT,
//     WHILE_STATEMENT,
//     FOR_STATEMENT,
//     FOREACH_STATEMENT,
//     RETURN_STATEMENT,
//     BREAK_STATEMENT,
//     CONTINUE_STATEMENT,
//     TRY_STATEMENT,
//     THROW_STATEMENT,
//     DECLARATION_STATEMENT,
//     STATEMENT_TYPE_COUNT_PLUS_1
// } StatementType;

void print_statement(StatementList *statementList)
{
     Statement   *statement = statementList->statement;

     print("[statement][%d,line=%d]\n", 
        statement->type, statement->line_number
        );
        
}

/*
struct DKC_Compiler_tag {
    MEM_Storage         compile_storage;
    FunctionDefinition  *function_list;
    int                 function_count;
    DeclarationList     *declaration_list;
    StatementList       *statement_list;
    int                 current_line_number;
    Block               *current_block;
    DKC_InputMode       input_mode;
    Encoding            source_encoding;
};
*/
void print_compiler(DKC_Compiler *compiler)
{
    println("**************Print  Compiler****************");

    println("==============FunctionDefinition,Count=%d==================", compiler->function_count);
    FunctionDefinition *function = compiler->function_list;
    while (function)
    {
        print_function(function);
        function = function->next;
    }

    println("==============DeclarationList==================");
    DeclarationList *declaration = compiler->declaration_list;
    while (declaration)
    {
        print_declaration(declaration);
        declaration = declaration->next;
    }

    println("==============StatementList==================111");
    StatementList *statement = compiler->statement_list;
    while (statement)
    {
        println("statement");
        print_statement(statement);
        statement = statement->next;
    }

    ;
}